/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package mopso;

/**
 *
 * @author robson
 */
public class ParticleData implements Comparable, Cloneable {

    private double[] positions;
    private double[] velocities;
    private double[] fitness;
    private int[] adaptiveGridIndexes;
    private double gValue;
    private int index;
    private boolean dominatedPbest;
    private double crowdingDistance;
    private int comparableDimension;
    private double distanceFromNeighbor;
    private Problem problem;

    public enum Sorting {
        SORTBYFITNESS, SORTBYCROWDINGDISTANCE, SORTBYNEIGHBORDISTANCE
    };
    
    private Sorting sortType;

    public ParticleData(Problem problem) {
        this.problem = problem;
        positions = new double[problem.getNDimensions()];

        for (int i = 0; i < problem.getNDimensions(); i++) {
            positions[i] = problem.getMinInitValue(i) + ((problem.getMaxInitValue(i) - problem.getMinInitValue(i)) * Math.random());
        }

        velocities = new double[problem.getNDimensions()];
        fitness = new double[problem.getFunctions().size()];
        adaptiveGridIndexes = new int[problem.getNObjectives()];
    }    
    
    public ParticleData(Problem problem, int index) {
        this.problem = problem;        
        this.index = index;
        positions = new double[problem.getNDimensions()];

        for (int i = 0; i < problem.getNDimensions(); i++) {
            positions[i] = problem.getMinInitValue(i) + ((problem.getMaxInitValue(i) - problem.getMinInitValue(i)) * Math.random());
        }

        velocities = new double[problem.getNDimensions()];
        fitness = new double[problem.getFunctions().size()];
        adaptiveGridIndexes = new int[problem.getNObjectives()];        
    }

    public double[] getPositions() {
        return positions;
    }

    public void setPositions(double[] positions) {
        this.positions = positions;
    }
    
    public void setPositions( double value, int index ) {
        this.positions[index] = value;
    }    

    public double[] getVelocities() {
        return velocities;
    }

    public void setVelocities(double[] velocities) {
        this.velocities = velocities;
    }

    public double[] getFitness() {
        return fitness;
    }

    public void setFitness(double[] fitness) {
        this.fitness = fitness;
    }
    
    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }    
    
    public Object clone() {
            ParticleData clone = new ParticleData( problem, index );
            clone.fitness = (double[]) this.fitness.clone();
            clone.positions = (double[]) this.positions.clone();
            clone.velocities = (double[]) this.velocities.clone();
            clone.adaptiveGridIndexes = (int[]) this.adaptiveGridIndexes.clone();
            clone.index = this.index;
            clone.gValue = this.gValue;
            clone.dominatedPbest = this.dominatedPbest;
            clone.crowdingDistance = this.crowdingDistance;
            clone.comparableDimension = this.comparableDimension;
            clone.distanceFromNeighbor = this.distanceFromNeighbor;
           
            return clone;
    }
    
    public int compareTo(Object obj) {
        
        if ( sortType == Sorting.SORTBYFITNESS ) {
            return ((Double) this.getFitness()[comparableDimension] ).compareTo((Double) ((ParticleData) obj).getFitness()[comparableDimension]  );            
        }
        
        else if ( sortType == Sorting.SORTBYCROWDINGDISTANCE ) {
            return ((Double) this.getCrowdingDistance() ).compareTo((Double) ((ParticleData) obj).getCrowdingDistance() );                        
        }

        else {
            return ((Double) this.getDistanceFromNeighbor() ).compareTo((Double) ((ParticleData) obj).getDistanceFromNeighbor() );
        }
    }    

    public boolean isDominatedPbest() {
        return dominatedPbest;
    }

    public void setDominatedPbest(boolean dominatedPbest) {
        this.dominatedPbest = dominatedPbest;
    }

    public double getCrowdingDistance() {
        return crowdingDistance;
    }

    public void setCrowdingDistance(double crowdingDistance) {
        this.crowdingDistance = crowdingDistance;
    }
    
    public Sorting getSortType() {
        return sortType;
    }

    public void setSortType(Sorting sortType) {
        this.sortType = sortType;
    }  
    
    public int getComparableDimension() {
        return comparableDimension;
    }

    public void setComparableDimension(int comparableDimension) {
        this.comparableDimension = comparableDimension;
    }     

    public double getGValue() {
        return gValue;
    }

    public void setGValue(double gValue) {
        this.gValue = gValue;
    }

    /**
     * @return the distanceFromNeighbor
     */
    public double getDistanceFromNeighbor() {
        return distanceFromNeighbor;
    }

    /**
     * @param distanceFromNeighbor the distanceFromNeighbor to set
     */
    public void setDistanceFromNeighbor(double distanceFromNeighbor) {
        this.distanceFromNeighbor = distanceFromNeighbor;
    }
    

    public int[] getAdaptiveGridIndexes() {
        return adaptiveGridIndexes;
    }

    public void setAdaptiveGridIndexes(int[] adaptiveGridIndexes) {
        this.adaptiveGridIndexes = adaptiveGridIndexes;
    } 
    
    public void setAdaptiveGridIndexes(int adaptiveGridIndex, int index) {
        this.adaptiveGridIndexes[index] = adaptiveGridIndex;
    }     
}
